2020网鼎杯玄武组_babyvm
本文为看雪论坛精华文章
看雪论坛作者ID:Craft_A
基本流程分析
IDA 分析,发现没有符号,有点函数跟的很深具体也不知道什么作用,这时结合动态调试,看看函数的输入输出,可以大概知道函数做了什么,并把函数根据功能进行重命名。
这里在正确 flag 的上面有一个函数,显然即使 check,传入的就是 str->大写 hex 的值。
下面进入check分析:
分析check时,这里还是通过动态调试,确定了几个函数。
1. 偏移D410 -->getmd5,传入一个 input,和一个 buffer 最终会计算根据 input 计算处 md5 存入 buffer:
结果表的值:
[0x0c5d83690,0x1f7902cc,0x978162ea,0x2fae3d15,0x1932a96c,0xceebfe91,0x4222669,0xaff6af42]
一共是8*4个字节。
总结一下
下面把 chek 中的基本的函数就分析大概流程分析完了,下面总结一下 check的基本流程:
1. 根据用户输入的信息计算出 md5,记作 input_md5(后面方便引用)
2. 根据用户输入计算出来一个100 byte 的表,记作 input_table
3. 算出 input_table 的 md5,记作 table_md5(这里后面也没有比较什么的,真是绝了,爆破吧)
4. 进入一个循环,根据开始,和结束条件,可以知道总共循环4次,并且会调用三个jisuan,分别传入的是input、input_md5、input_table。
先把input_md5 的4个字节放入v9,再进入sub_140075159出入计算(记作vm),计算的结果拼接 v9,这么一算得到的 v9 格式就是(input_md5,vm,input_md5+4,vm+4,....,input_md5+12,vm+12)总共 8*4 个字节,刚和和结果的表对应。
算法还原
vm流程算法
{0x1F7902CC,0x2FAE3D15,0x0CEEBFE91,0x0AFF6AF42}
先分析 vm 的流程,首先要知道传入 vm 中的表的结构,这里只能动态调试,把之前的反调试 patch 掉,开始调试,再 array 的地方下断点,观察array 的内存变化。
我的方法是,在每个 case 的偏移加上注释,动态调试一边关注 array 的变化,结合静态分析推断出每个 case 的作用,再在 x64debug 的对应位置做好标注,进行跟踪就很容易看出来规律了。
下面给一些重要的流程函数标记出来,然后跟踪找规律。
unsigned int r2l(unsigned int *input,unsigned int i){//i = 7~0 共执行了八轮 。整体3个函数共执行了2论
unsigned int tmp;
unsigned int tmp2;
tmp = *input >> i;
i=0x20-i;
tmp2 = *input << i;
return tmp | tmp2
}
3. case18 :有个函数,主要做的操作就是先左移再右移,每次移动产生的结果再在一起或运算得出结果,记作 l2r ( input,i ),这里的 i 已经是固定值了,就是 6 。
unsigned int l2r(unsigned int *input,unsigned int i){ //i=6
unsigned int tmp;
unsigned int tmp2;
tmp = *input << i;
i=0x20-i;
tmp2 = *input >> i;
return tmp | tmp2;
}
result = input
for(i=0;i<2;i++)
{
for(j=7;j>=0;j--)
{
result = r2l(result,j);
result = xor(result);
result = l2r(result,6);
}
}
继续往下跟
根据标注,其实追踪也能发现规律。
总结一下
解密思路
已经有了md5 的正确结果,以及 input 的正确结果,但是 md5_table 还不知道。
#include <windows.h>
#include <stdio.h>
byte table[100] = { 0 };
BOOL getMd5(BYTE *pbData, DWORD dwDataLen, BYTE *md5, DWORD &err)
{
HCRYPTPROV hProv;
if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
err = GetLastError();
return FALSE;
}
HCRYPTHASH hHash;
if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash))
{
err = GetLastError();
CryptReleaseContext(hProv, 0);
return FALSE;
}
if (!CryptHashData(hHash, pbData, dwDataLen, 0))
{
err = GetLastError();
CryptDestroyHash(hHash);
CryptReleaseContext(hProv, 0);
return FALSE;
}
DWORD dwSize;
DWORD dwLen = sizeof(dwSize);
CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)(&dwSize), &dwLen, 0);
BYTE* pHash = new BYTE[dwSize];
dwLen = dwSize;
CryptGetHashParam(hHash, HP_HASHVAL, pHash, &dwLen, 0);
for (DWORD i = 0; i < dwLen; i++) {
md5[i] = pHash[i];
}
delete[] pHash;
CryptDestroyHash(hHash);
CryptReleaseContext(hProv, 0);
return TRUE;
}
void getTable(byte mod) {
byte v8 = mod;
byte v10;
for (int k = 0; k < 100; k++) {
v10 = 0;
v8 ^= 0xc3;
*(byte*)(table + k) = v8;
for (int l = 0; l < 8; l++) {
v10 ^= (v8 >> l) & 1;
}
v8 = v10 | (2 * v8);
}
}
int main()
{
unsigned int vm[] = { 0x1F7902CC ,0x2FAE3D15 ,0xCEEBFE91 ,0xAFF6AF42 };
unsigned int md5[] = { 0xC5D83690 ,0x978162EA ,0x1932A96C ,0x4222669 };
BYTE md5_byte[20] = { 0x90,0x36,0xD8,0xC5,0xEA,0x62,0x81,0x97,0x6C,0xA9,0x32,0x19,0x69,0x26,0x22,0x04 };
byte md5_table[16];
unsigned int input;
byte input_src[16] = { 0 };
DWORD err;
for (int mod = 0; mod < 100; mod++) {//枚举模数
getTable(mod);
getMd5(table, 100,md5_table, err);
for (int p = 0; p < 4; p++) {
input = ~vm[p];
input = input ^ md5[p] ^ *((int*)md5_table+p);
for (int k = 0; k < 2; k++) {
for (int l = 0; l < 8; l++) {
input = ((input >> (6)) | (input << (0x20 - 6)));
input = input ^ 0x9E3779B9;
input = ((input << (l)) | (input >> (0x20 - l)));
}
}
//小端序
input_src[p * 4 + 3] = (byte)(input >> 24) & 0xff;
input_src[p * 4 + 2] = (byte)(input >> 16) & 0xff;
input_src[p * 4 + 1] = (byte)(input >> 8) & 0xff;
input_src[p * 4 + 0] = (byte)(input >> 0) & 0xff;
}
byte md5_2[16];
bool flag = true;
getMd5(input_src, 16, md5_2, err);
for (int i = 0; i < 16; i++) {
if (md5_2[i] != md5_byte[i]) {
flag = false;
break;
}
if (flag) {
printf("flag{%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n", input_src[0], input_src[1], input_src[2], input_src[3], input_src[4], input_src[5], input_src[6], input_src[7], input_src[8], input_src[9], input_src[10], input_src[11], input_src[12], input_src[13], input_src[14], input_src[15]);
}
}
}
return 0;
}
看雪ID:Craft_A
https://bbs.pediy.com/thread-259636.htm
推荐文章++++
好书推荐